home *** CD-ROM | disk | FTP | other *** search
- Subject: v07i037: An alternative to the BSD ruptime command
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: alasdair@ux.cs.man.ac.uk
- Mod.sources: Volume 7, Issue 37
- Archive-name: hostup
-
- [ This program can be very expensive to run. -r$ ]
-
- Inspired by the Tektronix TCP/IP 'hostup' command, I've done an
- equivalent thing for 4.[23] UNIX. Tried and tested on a 4.3 Beta
- Vax8600, and SUN3 version 3.0. It's primitive stuff, so feel free to
- enhance it to suit your own needs!
- Alasdair
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # hostup.1
- # Makefile
- # hostup.c
- # hostup.h
- # hostupd.c
- # This archive created: Sat Sep 6 16:01:51 1986
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'hostup.1'" '(1386 characters)'
- if test -f 'hostup.1'
- then
- echo shar: will not over-write existing file "'hostup.1'"
- else
- cat << \SHAR_EOF > 'hostup.1'
- .TH HOSTUP l "6 September 1986"
- .SH NAME
- hostup, hostupd \- network status report
- .SH SYNOPSIS
- .B hostup
- .SH DESCRIPTION
- .I hostup
- prints a list of network node names, with an indication of their
- reachability. It relies on a copy of
- .I hostupd
- running:
- .I hostupd
- polls machines in the /etc/hosts file and maintains
- a binary file of its results.
- .PP
- .I hostupd
- polls each machine by attempting to
- .IR connect (2)
- to an unused TCP port, and logging the type of error returned. This
- mechanism is a useful alternative to
- .IR ruptime (1),
- as it works with non-BSD machines, as well as with machines not
- running the ruptime daemon (such as diskless
- .B SUN
- workstations).
- .SH "SEE ALSO"
- ruptime(1)
- .br
- connect(2)
- .SH BUGS
- The polling process is
- .B slow
- (taking perhaps 75 minutes to complete one poll of the internal
- network at Manchester at weekends, when most machines are switched off)
- as it depends upon the
- .IR connect (2)
- timeout for each machine that is down.
- .PP
- .I hostupd
- currently sleeps for 5 minutes every time round the loop of machines:
- this is not strictly necessary if enough machines are down!
- .PP
- For machines connected to the Internet, polling every machine in
- /etc/hosts is probably a mistake.
- .PP
- The order of polling and the format of displaying the hosts is
- optimised for my network and my convenience.
- .SH AUTHOR
- Alasdair Rawsthorne (arawsthorne@uk.ac.man.cs.ux).
-
- SHAR_EOF
- if test 1386 -ne "`wc -c < 'hostup.1'`"
- then
- echo shar: error transmitting "'hostup.1'" '(should have been 1386 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'Makefile'" '(119 characters)'
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- cat << \SHAR_EOF > 'Makefile'
- hostup: hostup.c hostup.h
- cc -O -o hostup hostup.c -ltermcap
-
- hostupd: hostupd.c hostup.h
- cc -O -o hostupd hostupd.c
- SHAR_EOF
- if test 119 -ne "`wc -c < 'Makefile'`"
- then
- echo shar: error transmitting "'Makefile'" '(should have been 119 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'hostup.c'" '(2480 characters)'
- if test -f 'hostup.c'
- then
- echo shar: will not over-write existing file "'hostup.c'"
- else
- cat << \SHAR_EOF > 'hostup.c'
- #include <stdio.h>
-
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <sys/time.h>
-
- #include "hostup.h"
-
- #define FIELDWIDTH 11
-
- FILE *f; /* input file */
- struct timeval first, last; /* GMT of polls */
- struct timezone timezone; /* my offset */
- char * timeof();
- int currentpos = 0, width = 80; /* for formatting screen */
- char tbuf[1024];
-
- u_long lastnetwork = 0;
-
- struct perhost thishost;
-
- main()
- {
- long seconds;
- int cols;
- u_long network;
- if (tgetent(tbuf, getenv("TERM")) == 1) {
- if ((cols = tgetnum("co")) > 0) {
- width = cols;
- }
- }
- if ((f = fopen(FILENAME, "r")) == NULL) {
- perror(FILENAME);
- exit(1);
- }
- gettimeofday(&first, &timezone);
- last.tv_sec = 0;
- while (fread(&thishost, sizeof(thishost), 1, f) == 1) {
- network = ntohl(thishost.ph_to.sin_addr.s_addr);
- if (IN_CLASSA(network)) {
- network &= IN_CLASSA_NET;
- } else if (IN_CLASSB(network)) {
- network &= IN_CLASSB_NET;
- } else {
- network &= IN_CLASSC_NET;
- }
- if (network != lastnetwork) {
- lastnetwork = network;
- donl();
- }
- printstat(thishost.ph_name, thishost.ph_result);
- seconds = thishost.ph_time.tv_sec;
- if (first.tv_sec > seconds) {
- first.tv_sec = seconds;
- }
- if (last.tv_sec < seconds) {
- last.tv_sec = seconds;
- }
- }
- donl();
- printf("Polled from %s", timeof(&first));
- printf(" to %s; KEY: ", timeof(&last));
- printstat("Up", ECONNREFUSED);
- printstat("Down", ETIMEDOUT);
- printstat("UnReachable", ENETUNREACH);
- donl();
- exit(0);
- }
-
- char *
- timeof(tp)
- struct timeval *tp;
- {
- char *rp;
- struct tm *tm;
- tm = localtime(&tp->tv_sec);
- rp = asctime(tm);
- rp[19] = '\0'; /* truncate before timezone */
- return(rp + 11); /* return just the time */
- }
-
- printstat(name, errno)
- char *name;
- {
- int up = 0;
- char extra = ' ';
- switch(errno) {
- case ECONNREFUSED:
- up = 1;
- break;
- case 0:
- up = 1;
- extra = '!';
- break;
- case ETIMEDOUT:
- break;
- case ENETUNREACH:
- extra = '-';
- break;
- default:
- extra = '?';
- break;
- }
- if (up) {
- printf(" %s%c ", name, extra);
- } else {
- printf("(%s)%c", name, extra);
- }
- if (currentpos > (width - (2 * FIELDWIDTH))) {
- donl();
- } else {
- int i;
- currentpos += FIELDWIDTH;
- for (i = strlen(name)+3; i < FIELDWIDTH; i++) {
- putchar(' ');
- }
- }
- }
-
- donl()
- {
- if (currentpos) {
- putchar('\n');
- }
- currentpos = 0;
- }
- SHAR_EOF
- if test 2480 -ne "`wc -c < 'hostup.c'`"
- then
- echo shar: error transmitting "'hostup.c'" '(should have been 2480 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'hostup.h'" '(186 characters)'
- if test -f 'hostup.h'
- then
- echo shar: will not over-write existing file "'hostup.h'"
- else
- cat << \SHAR_EOF > 'hostup.h'
- #define MAXHOSTCHARS 12
- #define FILENAME "/usr/adm/host up"
-
- struct perhost {
- char ph_name[MAXHOSTCHARS];
- struct sockaddr_in ph_to;
- struct timeval ph_time;
- int ph_result;
- };
- SHAR_EOF
- if test 186 -ne "`wc -c < 'hostup.h'`"
- then
- echo shar: error transmitting "'hostup.h'" '(should have been 186 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'hostupd.c'" '(2349 characters)'
- if test -f 'hostupd.c'
- then
- echo shar: will not over-write existing file "'hostupd.c'"
- else
- cat << \SHAR_EOF > 'hostupd.c'
- #include <stdio.h>
-
- #include <sys/types.h>
- #include <sys/ioctl.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <netinet/in.h>
-
- #include <netdb.h>
-
- #define HISPORT 919 /* 'cos that's what tektronix use */
- #define MAXHOSTS 200
- #define SLEEPTIME 300 /* 5 mins wait at end of loop */
-
- #include "hostup.h"
-
- extern int errno;
-
- struct hostent *gethostent(), *host;
- int inetcomp();
- int s; /* socket number */
- FILE *f; /* output file */
- struct timezone timezone; /* somewhere to ignore it */
-
- struct perhost thishost[MAXHOSTS];
- int nohosts = 0;
-
- main()
- {
- if ((f = fopen(FILENAME, "w")) == NULL) {
- perror(FILENAME);
- exit(1);
- }
- readhosts(); /* find a table of hosts to poll */
- #ifndef DEBUG
- if (fork())
- exit(0);
- { int s;
- for (s = 0; s < 10; s++)
- if (s != fileno(f))
- (void) close(s);
- (void) open("/", 0);
- (void) dup2(0, 1);
- (void) dup2(0, 2);
- s = open("/dev/tty", 2);
- if (s >= 0) {
- ioctl(s, TIOCNOTTY, 0);
- (void) close(s);
- }
- }
- #endif
- while(1) {
- fseek(f, 0L, 0); /* keep writing from start */
- pollhosts();
- sleep(SLEEPTIME);
- }
- }
-
- readhosts()
- {
- while ((host = gethostent()) != NULL) {
- strncpy(thishost[nohosts].ph_name, host->h_name, MAXHOSTCHARS);
- thishost[nohosts].ph_name[MAXHOSTCHARS-1] = '\0';
- bzero((char *)&thishost[nohosts].ph_to, sizeof(thishost[nohosts].ph_to));
- bcopy(host->h_addr, (char *)&thishost[nohosts].ph_to.sin_addr, host->h_length);
- thishost[nohosts].ph_to.sin_family = host->h_addrtype;
- thishost[nohosts].ph_to.sin_port = HISPORT;
- nohosts++;
- if (nohosts == MAXHOSTS)
- break;
- }
- endhostent();
- qsort(thishost, nohosts, sizeof(thishost[0]), inetcomp);
- }
-
- inetcomp(a, b)
- struct perhost *a, *b;
- {
- return(ntohl(a->ph_to.sin_addr.s_addr) - ntohl(b->ph_to.sin_addr.s_addr));
- }
-
- pollhosts()
- {
- int i;
- for (i = 0; i < nohosts; i++) {
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s < 0) {
- #ifdef DEBUG
- perror("socket:");
- #endif
- exit(1);
- }
- if (connect(s, (char *)&thishost[i].ph_to,
- sizeof(thishost[i].ph_to)) < 0) {
- thishost[i].ph_result = errno;
- } else {
- thishost[i].ph_result = 0;
- }
- gettimeofday(&thishost[i].ph_time, &timezone);
- fwrite(&thishost[i], sizeof(thishost[i]), 1, f);
- fflush(f);
- (void) close(s); /* ! */
- }
- }
- SHAR_EOF
- if test 2349 -ne "`wc -c < 'hostupd.c'`"
- then
- echo shar: error transmitting "'hostupd.c'" '(should have been 2349 characters)'
- fi
- fi # end of overwriting check
- # End of shell archive
- exit 0
-